package com.kx.springmybatis.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * Pointcut 切入点，指定需要拦截的类
 * 利用注解指定环绕类型
 * Before 前置通知
 * After 后置通知
 * Around 环绕通知
 *
 * @ClassName MyAdvice
 * @Author Sun
 * @Date 2021/5/18 20:27
 */
@Component
@Aspect //定义一个切面，用于增强类
public class MyAdvice {

    //定义一个切表达式
    @Pointcut("execution(* com.kx..service.*.*(..))")
    public void aspectExpress() {

    }


    //    @Before("execution(* com.kx..service.*.*(..))")
    //JoinPoint 当前正在执行的方法的封装对象
    @Before("aspectExpress()")
    public void before(JoinPoint joinPoint) {
        //获取参数
        Object[] args = joinPoint.getArgs();
        System.out.println("参数"+args);
        System.out.println("资源路径"+joinPoint.getSourceLocation());
        //获取全类名
        Signature signature = joinPoint.getSignature();
        System.out.println("全类名"+signature);
        System.err.println("前置通知执行了");

    }

    //    @AfterReturning("execution(* com.kx..service.*.*(..))")
    //当前方法是在方法返回结果后执行,要想获取返回结果需用用一个参数接受,我们在方法中声明一个参数 result 来接收返回结果
    //同时需要在注解中添加returning属性来告诉 spring 返回结果放到哪个变量上,需要和接收的参数的形参名字保持一致
    @AfterReturning(value = "aspectExpress()",returning = "result")
    public void afterReturn(JoinPoint joinPoint,Object result) {
        //获取资源目标
        System.out.println("资源目标"+joinPoint.getTarget());
        System.out.println("返回结果"+result);
        System.err.println("afterReturn通知执行了");
    }

    //    @After("execution(* com.kx..service.*.*(..))")
    @After("aspectExpress()")
    public void after() {
        System.err.println("After通知执行了");
    }


    //    @Around("execution(* com.kx..service.*.*(..))")
//    @Around("aspectExpress()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.err.println("环绕通知的前半部分执行了");
        int i = 1 / 0;//我们可以停止原始方法的继续执行
        Object result = joinPoint.proceed();
        System.out.println("这是原始的返回结果"+result);
        System.err.println("环绕通知的后半部分执行了");
        return 1234;//此处的返回结果就是调用方真正拿到的结果
    }
}
